#include <workflow/WFFacilities.h>
#include <workflow/WFTaskFactory.h>
#include <workflow/HttpUtil.h>
#include <workflow/Workflow.h>
#include <workflow/WFHttpServer.h>
#include <signal.h>
#include <string>
#include <vector>
#include <iostream>

using std::string;
using std::vector;

struct SeriesContext {
    string password;
    protocol::HttpResponse *serverResp;
};

static WFFacilities::WaitGroup waitGroup(1);

void shutdown_server(int signum) {
    waitGroup.done();
    printf("done!\n");
}

void redisCallback(WFRedisTask *redisTask) {
    protocol::RedisValue value;
    redisTask->get_resp()->get_result(value); // 用户在redis数据库当中的密码

//    std::cout << value.string_value() << "\n";
    SeriesContext *context = (SeriesContext *) series_of(redisTask)->get_context();

    if (value.is_ok() && value.is_string() && value.string_value() == context->password) {
        context->serverResp->append_output_body("<html>OK</html>");
        printf("login success\n");
    } else {
        context->serverResp->append_output_body("<html>NO</html>");
        printf("login fail\n");
    }
}


// 解析表单数据
std::unordered_map<std::string, std::string> parse_form_data(const std::string &body) {
    std::unordered_map<std::string, std::string> form_data;
    size_t pos = 0;
    size_t end = 0;

    while ((end = body.find('&', pos)) != std::string::npos) {
        std::string token = body.substr(pos, end - pos);
        size_t eq_pos = token.find('=');

        if (eq_pos != std::string::npos) {
            std::string key = token.substr(0, eq_pos);
            std::string value = token.substr(eq_pos + 1);
            form_data[key] = value;
        }
        pos = end + 1;
    }

    // 最后一对键值对
    std::string token = body.substr(pos);
    size_t eq_pos = token.find('=');

    if (eq_pos != std::string::npos) {
        std::string key = token.substr(0, eq_pos);
        std::string value = token.substr(eq_pos + 1);
        form_data[key] = value;
    }

    return form_data;
}

// 处理 HTTP 请求的回调函数
void process(WFHttpTask *httpTask) {
    protocol::HttpRequest *req = httpTask->get_req();
    protocol::HttpResponse *resp = httpTask->get_resp();

    // 确保是 POST 请求并且 Content-Type 是 application/x-www-form-urlencoded
    if (string(req->get_method()) == "POST") {

        protocol::HttpHeaderCursor req_cursor(req);
        string content_type;
        req_cursor.find("Content-Type", content_type);

        if (std::string(content_type) == "application/x-www-form-urlencoded") {
            const void *body;
            size_t body_len;
            req->get_parsed_body(&body, &body_len);
            std::string body_str((const char *) body, body_len);

            // 解析表单数据
            auto form_data = parse_form_data(body_str);

            WFRedisTask *redisTask = WFTaskFactory::create_redis_task(
                    "*",
                    10,
                    redisCallback);

            redisTask->get_req()->set_request("get", {form_data["uname"]});
            series_of(httpTask)->push_back(redisTask);

            SeriesContext *context = new SeriesContext();
            context->password = form_data["pwd"];
            context->serverResp = resp;
            series_of(httpTask)->set_context(context);

        } else {
            resp->set_status_code("400 Bad Request");
            resp->append_output_body("Invalid Content-Type. Expected application/x-www-form-urlencoded.");
        }
    } else {
        resp->set_status_code("405 Method Not Allowed");
        resp->append_output_body("Only POST method is allowed.");
    }
}

int main() {
    signal(SIGINT, shutdown_server);
    /*创建一个server对象*/
    WFHttpServer server(process);

    /**
     * 启动server，之后server会等待客户端接入
     * 当有客户端接入时，创建一个序列，执行任务，任务的基本工作是process
     */
    if (server.start(8889) == 0) {
        waitGroup.wait();
        server.stop();
    } else {
        perror("server start failed");
        return -1;
    }

    return 0;
}